#pragma once
#include "Singleton.h"
#include "const.h"

class Request{
public:
    Request(unsigned int method, unsigned int version, std::string target, std::array<char, 8192> body)
    : _version(version), _method(method), _target(target), _body(body)
    {}

    unsigned int version()
    {
        return _version;
    }

    unsigned int method()
    {
        return _method;
    }

    std::string target()
    {
        return _target;
    }

    std::array<char, 8192> body()
    {
        return _body;
    }
private:
    unsigned int _version;
    unsigned int _method;
    std::string _target;
    std::array<char, 8192> _body;     //请求体
};

class Response{
public:
    Response(unsigned int version, unsigned int status)
    : _version(version), _status(status)
    {
        _header += "HTTP/" + std::to_string(_version) + " " + std::to_string(_status) + "\r\n";
    }
    void result(http_status result)
    {
        _status = result;
        //替换掉原来的状态码
        int start = _header.find(" ");  //从第一个空格处开始
        int end = _header.find(" ", start+1);    //到第二个空格处结束
        _header.replace(start, end, std::to_string(_status));
    }
    void keep_alive(bool keep_alive)
    {
        _keep_alive = keep_alive;
        int pos = _header.find("Connection: ");
        if (pos != std::string::npos)
        {
            //替换掉原来的连接类型
            int end = _header.find("\r\n", pos);
            _header.replace(pos, end, "Connection: " + std::string(_keep_alive ? "keep-alive" : "close"));
        }
        else
            _header += "Connection: " + std::string(_keep_alive ? "keep-alive" : "close") + "\r\n";
    }
    void content_length(std::string content_length)
    {
        int pos = _header.find("Content-Length: ");
        if (pos != std::string::npos)
        {
            //替换掉原来的
            int end = _header.find("\r\n", pos);
            _header.replace(pos, end, "Content-Length: " + content_length);
        }
        else
            _header += "Content-Length: " + content_length + "\r\n";
    }
    void accept_charset(std::string accept_charset)
    {
        int pos = _header.find("Accept-Charset: ");
        if (pos != std::string::npos)
        {
            //替换掉原来的
            int end = _header.find("\r\n", pos);
            _header.replace(pos, end, "Accept-Charset: " + accept_charset);
        }
        else
            _header += "Accept-Charset: " + accept_charset + "\r\n";
    }
    void content_type(std::string content_type)
    {
        int pos = _header.find("Content-Type: ");
        if (pos != std::string::npos)
        {
            //替换掉原来的
            int end = _header.find("\r\n", pos);
            _header.replace(pos, end, "Content-Type: " + content_type);
        }
        else
            _header += "Content-Type: " + content_type + "\r\n";
    }
    void accept_ranges(std::string accept_ranges)
    {
        int pos = _header.find("Accept-Ranges: ");
        if (pos != std::string::npos)
        {
            //替换掉原来的
            int end = _header.find("\r\n", pos);
            _header.replace(pos, end, "Accept-Ranges: " + accept_ranges);
        }
        else
            _header += "Accept-Ranges: " + accept_ranges + "\r\n";
    }
    std::array<char, 8192>& body()
    {
        return _body;
    }
private:
    unsigned int _version;
    std::array<char, 8192> _body;     //响应体
    std::string _header;         //响应头
    unsigned int _status;        //状态
    bool _keep_alive;           //是否保持连接
};

class HttpConnection : public std::enable_shared_from_this<HttpConnection>
{
public:
    HttpConnection(boost::asio::io_context &ioc); // 构造函数，用于初始化socket
    void Start();
    tcp::socket &GetSocket();
    friend class LogicSystem;
private:
    void PreParseGetParam();                      //对get请求的url进行预处理
    void HandleReq();                             //处理请求
    void CheckDeadline();                         //检测超时函数
    void WriteResponse();                         //发送响应
    void HandleNotFound();                        //处理未找到路径
    void HandleSuccess();                         //处理成功响应
    tcp::socket _socket;                          // 套接字，用于发送来的数据
    // boost::beast::flat_buffer _buffer{8192};      // 缓冲区，用于暂存数据
    std::array<char, 8192> _buffer;               //缓冲区
    http::request<http::dynamic_body> _request;   // 请求
    http::response<http::dynamic_body> _response; // 响应
    // The timer for putting a deadline on connection processing.
    boost::asio::steady_timer _deadline{
        _socket.get_executor(), std::chrono::seconds(60)};
    std::string _get_url;   //处理过后的url
    std::unordered_map<std::string, std::string> _get_params;   //get请求携带的参数
};